package com.fronald.httpclient;

import com.fronald.exceptions.PluginException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.fronald.libjutil.StrUtil;

public class HttpClient {

	private org.apache.commons.httpclient.HttpClient client = null;

	private int attemptsConnection = 1;

	private String proxyServer = "";

	private int proxyPort = 3128;

	private String proxyUsername = "";

	private String proxyPassword = "";

	private String host = "";

	private List<String> uris = new ArrayList();

	public HttpClient() {
		renew();
	}

	public synchronized List<String> postValues(String page, Map<String, String> values) throws PluginException {
		return postValues(page, values, null);
	}

	public synchronized List<String> postValues(String page, Map<String, String> values, Map<String, String> headers) throws PluginException {
		List rtn = new ArrayList();
		String h = prefixaHost(this.host);
		int i = 0;
		Exception ex = null;
		String body = "";
		if (!(page.startsWith("/"))) {
			page = "/" + page;
		}
		HttpMethod method = new PostMethod(h + page);
		for (String key : values.keySet()) {
			((PostMethod) method).addParameter(new NameValuePair(key, (String) values.get(key)));
		}

		if (headers != null) {
			for (String key : headers.keySet()) {
				method.addRequestHeader(new Header(key, headers.get(key)));
			}
		}

		if (i <= this.attemptsConnection) {
			try {
				ex = null;
				this.client.executeMethod(method);

				String redirectLocation = null;
				Header location = method.getResponseHeader("location");
				if (location != null) {
					redirectLocation = location.getValue();
				}

				if (!StrUtil.nvl(redirectLocation).equals("")) {
					method = new GetMethod(h + redirectLocation);
					this.client.executeMethod(method);
				}

				InputStream input = method.getResponseBodyAsStream();
				body = StrUtil.inputStreamToString(input);
				input.close();

				method.releaseConnection();
			} catch (Exception e) {
				ex = e;
				++i;

				method.releaseConnection();
			} finally {
				method.releaseConnection();
			}
		}
		if ((ex == null) && (!(StrUtil.nvl(body).equals("")))) {
			rtn.add(body);
		} else {
			throw new PluginException(ex.getMessage());
		}
		return rtn;
	}

	public synchronized List<String> getResults() throws PluginException {
		return getResults(null);
	}

	public synchronized List<String> getResults(Map<String, String> headers) throws PluginException {
		List rtn = new ArrayList();
		String h = prefixaHost(this.host);
		int i = 0;
		Exception ex = null;
		String body = "";
		for (Iterator it = getUris().iterator(); it.hasNext();) {
			String url = (String) it.next();
			if (i <= this.attemptsConnection) {
				if (!(url.startsWith("/"))) {
					url = "/" + url;
				}
				GetMethod method = new GetMethod(h + url);

				if (headers != null) {
					for (String key : headers.keySet()) {
						method.addRequestHeader(new Header(key, headers.get(key)));
					}
				}

				try {
					ex = null;
					this.client.executeMethod(method);

					String redirectLocation = null;
					Header location = method.getResponseHeader("location");
					if (location != null) {
						redirectLocation = location.getValue();
					}

					if (!StrUtil.nvl(redirectLocation).equals("")) {
						method = new GetMethod(h + redirectLocation);
						this.client.executeMethod(method);
					}

					InputStream input = method.getResponseBodyAsStream();
					body = StrUtil.inputStreamToString(input);
					input.close();

					method.releaseConnection();
				} catch (Exception e) {
					ex = e;
					++i;

					method.releaseConnection();
				} finally {
					method.releaseConnection();
				}
			}
			if ((ex == null) && (!(StrUtil.nvl(body).equals("")))) {
				rtn.add(body);
			} else {
				throw new PluginException(ex.getMessage());
			}
		}
		return rtn;
	}

	private String prefixaHost(String h) {
		if ((!(h.startsWith("http://"))) && (!(h.startsWith("https://")))) {
			h = "http://" + h;
		}
		return h;
	}

	public void renew() {
		HttpConnectionManager conM = new MultiThreadedHttpConnectionManager();
		this.client = new org.apache.commons.httpclient.HttpClient(conM);
		this.client.getParams().setParameter("http.connection.stalecheck", Boolean.valueOf(false));
		this.client.getParams().setBooleanParameter("http.protocol.allow-circular-redirects", true);
	}

	public void setProxy(String server, int port, String username, String password) {
		this.client.getHostConfiguration().setProxy(server, port);
		if (!(StrUtil.nvl(username).equals(""))) {
			this.client.getState().setProxyCredentials(new AuthScope(server, port, null), new UsernamePasswordCredentials(username, StrUtil.nvl(password)));
		}
		this.proxyServer = server;
		this.proxyPort = port;
		this.proxyPassword = password;
		this.proxyUsername = username;
	}

	public void setSocketTimeOut(int miliseconds) {
		this.client.getHttpConnectionManager().getParams().setSoTimeout(miliseconds);
	}

	public int getSocketTimeOut() {
		return this.client.getHttpConnectionManager().getParams().getSoTimeout();
	}

	public void setConnTimeOut(int miliseconds) {
		this.client.getHttpConnectionManager().getParams().setConnectionTimeout(miliseconds);
	}

	public int getConnTimeOut() {
		return this.client.getHttpConnectionManager().getParams().getConnectionTimeout();
	}

	public int getAttemptsConnection() {
		return this.attemptsConnection;
	}

	public void setAttemptsConnection(int attemptsConnection) {
		this.attemptsConnection = attemptsConnection;
	}

	public String getHost() {
		return this.host;
	}

	public void setHost(String host) {
		this.host = host;
	}

	public List<String> getUris() {
		return this.uris;
	}

	public void setUris(List<String> uris) {
		this.uris = uris;
	}

}
